﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

//class Date
//{
//
//public:
//	Date(int year = 1, int month = 1, int day = 1)
//	{
//		_year = year;
//		_month = month;
//		_day = day;
//	}
//	// void Print(const Date* const this) const
//	void Print() const
//	{
//		cout << _year << "-" << _month << "-" << _day << endl;
//	}
//private:
//	int _year;
//	int _month;
//	int _day;
//
//};
//int main()
//{
//	// 这⾥⾮const对象也可以调⽤const成员函数是⼀种权限的缩⼩
//	Date d1(2024, 7, 5);//对象实例化
//	d1.Print();//普通对象进行print的调用，括号内存在隐藏的this指针
//	const Date d2(2024, 8, 5);
//	/*
//	&d  ->const Date*
//	这个this指针的类型是Date*的
//	我们这里的d2是被const修饰的，d2是不能修改的
//	但是我们的this指针是被const修饰的
//	两个是不一样的
//	所以我们需要将this指针的const放到*左边，但是我们没办法做到这个，所以就在函数的后面加上const来实现这个要求了
//
//	这个const在*左边，那么就是修饰对象的，如果在右边的话就是修饰的是指针本身了
//	那么这里就是修饰的指向的内容，d不能进行修改
//
//	我们上面的Print(Date* const this)
//	那么const修饰的就是指针
//	这个const是可以进行忽略的
//
//	修饰本身的const不涉及权限的放大和缩小
//	我被我拷贝一份，给你进行赋值操作
//	又不改变我本身
//
//	指向内容的const才会存在权限的放大和缩小的问题的
//
//	上面的是const Date *
//	我指向的内容我都改变不了
//	const Date *不能给Date *
//	就属于权限的放大的问题
//	Date *是可以改变的，但是const Date *是不能改变的
//	权限被放大了
//
//	我们把Print括号内改成const Date*就不存在权限放大的问题了
//	但是没有办法进行修改
//	因为this指针是隐藏的，我们是加不了const的
//
//	所以祖师爷想了一个办法，选择在函数参数列表后面加上const
//
//	这个const修饰的不是this指针本身，而是this指针指向的内容
//
//	那么我们在函数参数列表后面加上const的话就相当于
//	Print(const Date*const this)
//
//	const修饰指向内容的时候才涉及到权限放大和缩小的内容 
//
//	在Print函数后面加上const就是权限的平移
//	*/
//
//	/*
//	后面加上const普通对象也是可以进行使用的
//	Date d1(2024, 7, 5);
//	&d1->Date*  这个Date*可读可写
//	然后传到Print函数内的this指针变成只能读的
//	那么就是权限的缩小了
//	权限不能放大，但是权限能缩小
//	*/
//
//
//
//	d2.Print();
//	return 0;
//}

class Time
{
public :
	Time(int hour=0)
		: _hour(hour)
	{
		cout << "Time()" << endl;
	}
private:
	int _hour;
};
class Date
{
public :
	Date(int year = 2, int month = 2, int day = 2)
		: _year(year)
		, _month(month)
		, _day(day)
	{
		// error C2512: “Time”: 没有合适的默认构造函数可⽤
		// error C2530 : “Date::_ref” : 必须初始化引⽤
		// error C2789 : “Date::_n” : 必须初始化常量限定类型的对象
	} 
	void Print() const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year=1;
	int _month=1;
	int _day=1;
	
	Time _t=10; // 我们初始化列表中没有对_t进行初始化的操作,但是我们也能调用默认构造的
	
};
int main()
{
	int i = 0;
	Date d1(2024,5,1);
	d1.Print();
	return 0;
}
//通过调试我们能知道我们尽管在初始化列表中没有进行_t的初始化的操作，但是我们仍然进行了_t的初始化操作
//调用了上面的默认构造
/*
C++11⽀持在成员变量声明的位置给缺省值，这个缺省值
主要是给没有显⽰在初始化列表初始化的成员使⽤的

我们可以在声明的时候给上缺省值，这个声明是给初始化列表的

如果我们在初始化列表中给出了初始化的话，那么我们下面变量的缺省操作就会被省略了，直接用上我们给的值
显示给了初始化，那么就不会尊崇声明的时候的缺省值

缺省值就是最卑微的，如果什么都没给的话，那么就是用缺省值
*/